package com.zatech.cgnci.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zatech.cgnci.project.base.constant.ClaimConstant;
import com.zatech.cgnci.project.base.context.UserContext;
import com.zatech.cgnci.project.base.enums.*;
import com.zatech.cgnci.project.base.exception.GlobalException;
import com.zatech.cgnci.project.base.utils.BeanUtils;
import com.zatech.cgnci.project.base.utils.ConvertUtils;
import com.zatech.cgnci.project.base.utils.VerifyUtils;
import com.zatech.cgnci.project.dto.*;
import com.zatech.cgnci.project.entity.*;
import com.zatech.cgnci.project.mapper.*;
import com.zatech.cgnci.project.service.*;
import com.zatech.cgnci.project.vo.*;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 准备金记录表 服务实现类
 * </p>
 *
 * @author Generator
 * @since 2024-12-23
 */
@Service
@RequiredArgsConstructor
public class CgnciClaimReserveServiceImpl extends ServiceImpl<CgnciClaimReserveMapper, CgnciClaimReserveDO> implements CgnciClaimReserveService {
    @Autowired
    private IApprovalService approvalService;
    @Autowired
    private CgnciApprovalInfoMapper approvalInfoMapper;
    @Autowired
    private CgnciApprovalRecordMapper approvalRecordMapper;
    @Autowired
    private CgnciClaimCaseTaskService claimCaseTaskService;
    @Autowired
    private CgnciClaimReserveDetailMapper reserveDetailMapper;
    @Autowired
    private CgnciClaimCaseService claimCaseService;
    @Autowired
    private CgnciClaimCaseTaskMapper claimCaseTaskMapper;
    @Resource
    private CgnciClaimPolicyMapper claimPolicyMapper;
    @Resource
    private CgnciClaimPolicyTaskMapper policyTaskMapper;
    @Resource
    private CgnciClaimSettlementService claimSettlementService;
    @Resource
    private CgnciClaimReserveTaskMapper reserveTaskMapper;
    @Autowired
    private CgnciOperationLogsService cgnciOperationLogsService;
    @Resource
    private CgnciClaimReserveDetailTaskMapper reserveDetailTaskMapper;
    @Resource
    private CgnciApprovalConfigMapper approvalConfigMapper;
    @Resource
    private CgnciAccessoryService accessoryService;
    @Resource
    private CgnciClaimReserveHistoryService claimReserveHistoryService;
    @Autowired
    private CgnciClaimReserveHistoryService cgnciClaimReserveHistoryService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addTask(CgnciClaimReserveDTO reserveDTO, boolean backStatus) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        // 保存准备金基本信息
        CgnciClaimReserveTaskDO reserveTaskDO = ConvertUtils.convert(reserveDTO, CgnciClaimReserveTaskDO.class);
        if (reserveDTO.getFlowTaskType()) {
            reserveTaskDO.setTaskStatus(ClaimTaskStatusEnum.CHECKING.getCode());   //审核中
        } else {
            reserveTaskDO.setTaskStatus(backStatus ? ClaimTaskStatusEnum.BACK.getCode() : ClaimTaskStatusEnum.INPUT.getCode());
        }
//          Integer count =  reserveTaskMapper.selectCount(new LambdaQueryWrapper<CgnciClaimReserveTaskDO>()
//                    .eq(CgnciClaimReserveTaskDO::getTaskNo, reserveDTO.getTaskNo())
//                    .eq(CgnciClaimReserveTaskDO::getTaskStatus,ClaimTaskStatusEnum.INPUT.getCode()));
//          if(count>0) {
        reserveTaskMapper.delete(new LambdaQueryWrapper<CgnciClaimReserveTaskDO>()
                .eq(CgnciClaimReserveTaskDO::getTaskNo, reserveDTO.getTaskNo()));
        reserveDetailTaskMapper.delete(new LambdaQueryWrapper<CgnciClaimReserveDetailTaskDO>()
                .eq(CgnciClaimReserveDetailTaskDO::getTaskNo, reserveDTO.getTaskNo()));
        // }
        reserveTaskDO.setTaskNo(reserveDTO.getTaskNo());
        reserveTaskDO.setCreator(user.getNameAndCode());
        reserveTaskDO.setUpdater(user.getNameAndCode());
        reserveTaskDO.setCreateTime(new Date());
        reserveTaskMapper.insert(reserveTaskDO);

        // 保存准备金明细
        for (CgnciClaimReserveDTO.ReserveDetailDTO detail : reserveDTO.getDetails()) {
            CgnciClaimReserveDetailTaskDO detailTaskDO = ConvertUtils.convert(detail, CgnciClaimReserveDetailTaskDO.class);
            detailTaskDO.setReserveId(reserveTaskDO.getReserveId());
            detailTaskDO.setTaskNo(reserveDTO.getTaskNo());
            detailTaskDO.setCreator(user.getNameAndCode());
            detailTaskDO.setUpdater(user.getNameAndCode());
            detailTaskDO.setCreateTime(new Date());
            reserveDetailTaskMapper.insert(detailTaskDO);
        }
        return reserveTaskDO.getReserveId();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public String saveOrUpdateReserve(CgnciClaimReserveDTO reserveDTO) {
        UserEntity user = UserContext.getUser();
        String taskNo = null;
        if (reserveDTO.getRate().compareTo(BigDecimal.ZERO) == 0) {
            throw new GlobalException(ResponseCodeEnum.PARAMS_ILLEGAL, "汇率不允许为0");
        }
        Integer taskCount = this.baseMapper.selectCount(new LambdaQueryWrapper<CgnciClaimReserveDO>()
                .eq(CgnciClaimReserveDO::getCaseNo, reserveDTO.getCaseNo())
                .eq(CgnciClaimReserveDO::getTaskStatus, ClaimTaskStatusEnum.CHECKING.getCode()));
        if (taskCount > 0) {
            throw new GlobalException(ResponseCodeEnum.PARAMS_ILLEGAL, "当前已有准备金计提/调整进行中的数据");
        }
        //保存数据判断
        List<String> status = new ArrayList<>();
        status.add(ClaimTaskStatusEnum.INPUT.getCode());
        status.add(ClaimTaskStatusEnum.BACK.getCode());
        List<CgnciClaimReserveTaskDO> reserveTaskDOS = reserveTaskMapper.selectList(new LambdaQueryWrapper<CgnciClaimReserveTaskDO>()
                .eq(CgnciClaimReserveTaskDO::getCaseNo, reserveDTO.getCaseNo())
                .in(CgnciClaimReserveTaskDO::getTaskStatus, status));
        if (CollectionUtils.isEmpty(reserveTaskDOS)) {
            if (reserveDTO.getFlowTaskType()) {
                throw new GlobalException(ResponseCodeEnum.PARAMS_ILLEGAL, "请先保存数据后再提交审核");
            }
            taskNo = claimCaseTaskService.generateTaskNo();
            reserveDTO.setTaskNo(taskNo);
        } else {
            //安全扫描问题修改成从查询取taskNo（请勿优化）
            taskNo = reserveTaskDOS.get(0).getTaskNo();
        }

        CgnciClaimCaseTaskDO backCaseTaskDO = claimCaseTaskMapper.selectOne(new LambdaQueryWrapper<CgnciClaimCaseTaskDO>()
                .eq(CgnciClaimCaseTaskDO::getTaskNo, reserveDTO.getTaskNo())
                .eq(CgnciClaimCaseTaskDO::getTaskStatus, ClaimTaskStatusEnum.BACK.getCode()));
        boolean backStatus = VerifyUtils.isNotEmpty(backCaseTaskDO);

        // 更新修改准备金任务
        Integer countTask = reserveTaskMapper.selectCount(new LambdaQueryWrapper<CgnciClaimReserveTaskDO>()
                .eq(CgnciClaimReserveTaskDO::getTaskNo, reserveDTO.getTaskNo()));

        // 镜像数据生成条件查询
        Integer count = reserveTaskMapper.selectCount(new LambdaQueryWrapper<CgnciClaimReserveTaskDO>()
                .eq(CgnciClaimReserveTaskDO::getCaseNo, reserveDTO.getCaseNo())
                .eq(CgnciClaimReserveTaskDO::getTaskStatus, ClaimTaskStatusEnum.DONE.getCode()));

        // 新增或更新我的案件-准备金
        adjust(reserveDTO, backStatus);

        // 新增或更新我的任务-准备金
        addTask(reserveDTO, backStatus);


        if (reserveDTO.getFlowTaskType()) {//提交审核
            // 校验当次计提/调整金额是否超过100万美元
            if (VerifyUtils.isNotEmpty(reserveDTO.getIsExceed()) && "1".equals(reserveDTO.getIsExceed())) {
                if (VerifyUtils.isEmpty(reserveDTO.getAccessoryDTOList())) {
                    throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "对于拟提取准备金超100万美元的重大赔案，应召开自保业务合议组会议并上传“重大赔案准备金拨备合议组建议”");
                }
                // 查询文件是否有倒签资料
                List<Long> accIds = reserveDTO.getAccessoryDTOList().stream().map(CgnciClaimReserveDTO.AccessoryDTO::getAccId).collect(Collectors.toList());
                List<CgnciAccessoryDO> accessoryList = accessoryService.listByIds(accIds);
                CgnciAccessoryDO accessory = accessoryList.stream().filter(acc -> "meetSummary".equals(acc.getAccType())).findFirst().orElse(null);
                if (VerifyUtils.isEmpty(accessory)) {
                    throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "对于拟提取准备金超100万美元的重大赔案，应召开自保业务合议组会议并上传“重大赔案准备金拨备合议组建议”");
                }
            }

            // TODO 插入准备金历史表
            List<CgnciClaimReserveDTO.ReserveDetailDTO> details = reserveDTO.getDetails();
            details.forEach(detail -> {
                CgnciClaimReserveHistoryDO historyDO = ConvertUtils.convert(detail, CgnciClaimReserveHistoryDO.class);
                // 跟进案件号，任务号，险种查询是否存在数据
                CgnciClaimReserveHistoryDO existHistoryDO = claimReserveHistoryService.getOne(new LambdaQueryWrapper<CgnciClaimReserveHistoryDO>()
                        .eq(CgnciClaimReserveHistoryDO::getCaseNo, reserveDTO.getCaseNo())
                        .eq(CgnciClaimReserveHistoryDO::getTaskNo, reserveDTO.getTaskNo())
                        .eq(CgnciClaimReserveHistoryDO::getRiskType, detail.getRiskType()));
                if (VerifyUtils.isNotEmpty(existHistoryDO)) {
                    historyDO.setHistoryId(existHistoryDO.getHistoryId());
                }
                historyDO.setCaseNo(reserveDTO.getCaseNo());
                historyDO.setTaskNo(reserveDTO.getTaskNo());
                historyDO.setTaskType(count > 0 ? ClaimTaskTypeEnum.RESERVES_ADJUST.getCode() : ClaimTaskTypeEnum.RESERVES_PROVISION.getCode());
                historyDO.setTaskStatus(ClaimTaskStatusEnum.CHECKING.getCode());
                historyDO.setRate(reserveDTO.getRate());
                historyDO.setReserveId(reserveDTO.getReserveId());
                historyDO.setCreator(user.getNameAndCode());
                historyDO.setUpdater(user.getNameAndCode());
                claimReserveHistoryService.saveOrUpdate(historyDO);
            });

            // 更新任务状态
            updateCaseTask(reserveDTO.getTaskNo(), ClaimTaskStatusEnum.CHECKING.getCode(), user);

            FlowTaskSubmitDTO flowTaskDTO = new FlowTaskSubmitDTO();
            // 判断状态是否为‘退回录入中’，并且流程已经创建无需再次创建任务
            CgnciApprovalInfoDO approvalInfoDO = approvalInfoMapper.selectOne(new LambdaQueryWrapper<CgnciApprovalInfoDO>()
                    .eq(CgnciApprovalInfoDO::getFormNo, reserveDTO.getTaskNo())
                    .eq(CgnciApprovalInfoDO::getApprovalConfigGroupId, "016")
                    .eq(CgnciApprovalInfoDO::getIsEnd, 0));
            if (VerifyUtils.isNotEmpty(approvalInfoDO)) {
                flowTaskDTO.setApprovalInfoId(approvalInfoDO.getApprovalInfoId());
            }
            if (VerifyUtils.isEmpty(approvalInfoDO)) {
                // 否则创建任务,绑定工作流formId. 并且关联工作台的跳转地址url以及参数
                ApprovalInfoVO infoVO = approvalService.create(FlowTaskCreateDTO.builder().approvalConfigGroupId("016").formId(reserveDTO.getTaskNo()).formNo(reserveDTO.getTaskNo())
                        .redirectionUrl("/api/claim/reserve/task/detailTask").redirectionParam(reserveDTO.getTaskNo()).redirectionDesc("跳转准备金计提详情").build());
                flowTaskDTO.setApprovalInfoId(infoVO.getApprovalInfoId());
            }
            flowTaskDTO.setFormId(reserveDTO.getTaskNo());
            approvalService.submit(flowTaskDTO);
            String content = String.format("立案号：%s;准备金计提/调整任务号：%s", reserveDTO.getCaseNo(), taskNo);
            if (count > 0) {
                saveLog(reserveDTO.getCaseNo(), OperationTypeEnum.SUBMIT_RESERVE_CHANGE, user.getUsername(), content);
            } else {
                saveLog(reserveDTO.getCaseNo(), OperationTypeEnum.SUBMIT_RESERVE, user.getUsername(), content);
            }
        } else {
            // 不为空代表退回录入中
            if (VerifyUtils.isNotEmpty(backCaseTaskDO)) {
                updateCaseTask(reserveDTO.getTaskNo(), ClaimTaskStatusEnum.BACK.getCode(), user);
                return reserveDTO.getTaskNo();
            }

            if (countTask > 0) {
                updateCaseTask(reserveDTO.getTaskNo(), ClaimTaskStatusEnum.INPUT.getCode(), user);
                return reserveDTO.getTaskNo();
            }

            //镜像数据生成
            if (count > 0) {
                claimCaseTaskService.copyCreateCaseTask(user, reserveDTO.getCaseNo(), reserveDTO.getTaskNo(), ClaimTaskTypeEnum.RESERVES_ADJUST.getCode());
            } else {
                claimCaseTaskService.copyCreateCaseTask(user, reserveDTO.getCaseNo(), reserveDTO.getTaskNo(), ClaimTaskTypeEnum.RESERVES_PROVISION.getCode());
            }
        }
        return taskNo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void adjust(CgnciClaimReserveDTO reserveDTO, boolean backStatus) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        // 更新或新增准备金信息
        CgnciClaimReserveDO reserveDO = ConvertUtils.convert(reserveDTO, CgnciClaimReserveDO.class);
        if (reserveDTO.getFlowTaskType()) {
            reserveDO.setTaskStatus(ClaimTaskStatusEnum.CHECKING.getCode());   //审核中
        } else {
            reserveDO.setTaskStatus(backStatus ? ClaimTaskStatusEnum.BACK.getCode() : ClaimTaskStatusEnum.INPUT.getCode());
        }
        reserveDO.setUpdater(user.getNameAndCode());
        this.saveOrUpdate(reserveDO);

        // 删除原有明细-如果有的话
        reserveDetailMapper.delete(new LambdaQueryWrapper<CgnciClaimReserveDetailDO>()
                .eq(CgnciClaimReserveDetailDO::getReserveId, reserveDO.getReserveId()));

        // 保存新的明细
        for (CgnciClaimReserveDTO.ReserveDetailDTO detail : reserveDTO.getDetails()) {
            CgnciClaimReserveDetailDO detailDO = ConvertUtils.convert(detail, CgnciClaimReserveDetailDO.class);
            detailDO.setReserveId(reserveDO.getReserveId());
            detailDO.setCreator(user.getNameAndCode());
            detailDO.setUpdater(user.getNameAndCode());
            reserveDetailMapper.insert(detailDO);
        }

        // 更新或者保存准备金附件
        List<CgnciClaimReserveDTO.AccessoryDTO> accessoryDTOList = reserveDTO.getAccessoryDTOList();
        if (VerifyUtils.isNotEmpty(accessoryDTOList)) {
            List<CgnciAccessoryDO> accessoryList = new ArrayList<>();
            accessoryDTOList.forEach(accessory -> {
                CgnciAccessoryDO accessoryDO = accessoryService.getById(accessory.getAccId());
                // 文件绑定业务数据
                accessoryDO.setBusinessNo(reserveDO.getCaseNo());
                accessoryDO.setUploadNode(ClaimFlowEnum.CLAIM_RESERVE.getCode());
                accessoryList.add(accessoryDO);
            });
            accessoryService.saveOrUpdateBatch(accessoryList);
        }

    }

    @Override
    public CgnciClaimReserveVO detail(String caseNo, String isSendBack) {
        CgnciClaimReserveVO claimReserveVO = this.baseMapper.getDetail(caseNo, isSendBack);
        if (VerifyUtils.isEmpty(claimReserveVO)) {
            return null;
        }
        List<CgnciAccessoryDO> accessoryList = accessoryService.list(new LambdaQueryWrapper<CgnciAccessoryDO>()
                .eq(CgnciAccessoryDO::getBusinessNo, caseNo)
                .eq(CgnciAccessoryDO::getUploadNode, ClaimFlowEnum.CLAIM_RESERVE.getCode()));
        claimReserveVO.setAccessoryVOList(ConvertUtils.convert(accessoryList, CgnciAccessoryVO.class));
        return claimReserveVO;
    }

    @Override
    public CgnciClaimReserveVO detailTask(String taskNo) {
        CgnciClaimReserveTaskDO reserveTaskDO = reserveTaskMapper.selectOne(
                new LambdaQueryWrapper<CgnciClaimReserveTaskDO>()
                        .eq(CgnciClaimReserveTaskDO::getTaskNo, taskNo)
        );
        if (Objects.isNull(reserveTaskDO)) {
            return null;
        }
        List<CgnciClaimReserveDetailTaskDO> reserveDetailTaskDOS = reserveDetailTaskMapper.selectList(
                new LambdaQueryWrapper<CgnciClaimReserveDetailTaskDO>()
                        .eq(CgnciClaimReserveDetailTaskDO::getTaskNo, taskNo)
        );
        if (CollectionUtils.isEmpty(reserveDetailTaskDOS)) {
            throw new GlobalException(ResponseCodeEnum.PARAMS_ILLEGAL, "taskNo有误,准备金详情数据为空");
        }
        CgnciClaimReserveVO reserveTaskVO = ConvertUtils.convert(reserveTaskDO, CgnciClaimReserveVO.class);
        reserveTaskVO.setDetails(ConvertUtils.convert(reserveDetailTaskDOS, CgnciClaimReserveVO.ReserveDetailVO.class));
        List<CgnciAccessoryDO> accessoryList = accessoryService.list(new LambdaQueryWrapper<CgnciAccessoryDO>()
                .eq(CgnciAccessoryDO::getBusinessNo, reserveTaskDO.getCaseNo())
                .eq(CgnciAccessoryDO::getUploadNode, ClaimFlowEnum.CLAIM_RESERVE.getCode()));
        reserveTaskVO.setAccessoryVOList(ConvertUtils.convert(accessoryList, CgnciAccessoryVO.class));
        return reserveTaskVO;
    }

    @Override
    public CgnciClaimReserveVO detail(String caseNo) {
        CgnciClaimReserveDO reserveDO = this.baseMapper.selectOne(
                new LambdaQueryWrapper<CgnciClaimReserveDO>()
                        .eq(CgnciClaimReserveDO::getCaseNo, caseNo));
        if (Objects.isNull(reserveDO)) {
            return new CgnciClaimReserveVO();
        }
        List<CgnciClaimReserveDetailDO> reserveDetailDOS = reserveDetailMapper.selectList(
                new LambdaQueryWrapper<CgnciClaimReserveDetailDO>()
                        .eq(CgnciClaimReserveDetailDO::getReserveId, reserveDO.getReserveId())
        );
        if (CollectionUtils.isEmpty(reserveDetailDOS)) {
            throw new GlobalException(ResponseCodeEnum.PARAMS_ILLEGAL, "caseNo" + caseNo + "有误,准备金详情数据为空");
        }
        CgnciClaimReserveVO reserveTaskVO = ConvertUtils.convert(reserveDO, CgnciClaimReserveVO.class);
        reserveTaskVO.setDetails(ConvertUtils.convert(reserveDetailDOS, CgnciClaimReserveVO.ReserveDetailVO.class));
        List<CgnciAccessoryDO> accessoryList = accessoryService.list(new LambdaQueryWrapper<CgnciAccessoryDO>()
                .eq(CgnciAccessoryDO::getBusinessNo, reserveDO.getCaseNo())
                .eq(CgnciAccessoryDO::getUploadNode, ClaimFlowEnum.CLAIM_RESERVE.getCode()));
        reserveTaskVO.setAccessoryVOList(ConvertUtils.convert(accessoryList, CgnciAccessoryVO.class));
        return reserveTaskVO;
    }

    @Override
    public void verify(String caseNo) {
        List<String> taskType = new ArrayList<>();
        taskType.add(ClaimTaskTypeEnum.PREPAY.getCode());
        taskType.add(ClaimTaskTypeEnum.CLOSE.getCode());
        taskType.add(ClaimTaskTypeEnum.RESERVES_PROVISION.getCode());
        taskType.add(ClaimTaskTypeEnum.RESERVES_ADJUST.getCode());
        List<String> taskStatus = new ArrayList<>();
        //taskStatus.add(ClaimTaskStatusEnum.INPUT.getCode());
        taskStatus.add(ClaimTaskStatusEnum.CHECKING.getCode());
        taskStatus.add(ClaimTaskStatusEnum.BACK.getCode());
        List<CgnciClaimCaseTaskDO> taskDOS = claimCaseTaskMapper.selectList(new LambdaQueryWrapper<CgnciClaimCaseTaskDO>()
                .eq(CgnciClaimCaseTaskDO::getCaseNo, caseNo)
                .in(CgnciClaimCaseTaskDO::getTaskType, taskType)
                .in(CgnciClaimCaseTaskDO::getTaskStatus, taskStatus));
        if (CollectionUtils.isNotEmpty(taskDOS)) {
            throw new GlobalException(ResponseCodeEnum.PARAMS_ILLEGAL, "当前立案中已有" + ClaimTaskTypeEnum.getEnumByCode(taskDOS.get(0).getTaskType()).getName() + "状态为：" + ClaimTaskStatusEnum.getEnumByCode(taskDOS.get(0).getTaskStatus()).getDescr()
                    + "的数据，如需操作请先注销当前任务后在我的案件处理中发起准备金计提/调整.");
        }
    }


    @Override
    public void approve(CgnciClaimCaseCheckDTO flowTaskDTO) {
        UserEntity user = UserContext.getUser();
        // 校验是否存在
        CgnciClaimReserveTaskDO reserveTaskDO = reserveTaskMapper.selectOne(
                new LambdaQueryWrapper<CgnciClaimReserveTaskDO>()
                        .eq(CgnciClaimReserveTaskDO::getTaskNo, flowTaskDTO.getTaskNo())
        );
        if (VerifyUtils.isEmpty(reserveTaskDO)) {
            throw new GlobalException(ResponseCodeEnum.PARAMS_ILLEGAL);
        }
        FlowTaskApprovalDTO approvalDTO = new FlowTaskApprovalDTO();
        approvalDTO.setFormNo(flowTaskDTO.getTaskNo());
        approvalDTO.setFormId(flowTaskDTO.getTaskNo());
        FlowTaskVO approve = approvalService.approve(approvalDTO);
        reserveTaskDO.setTaskStatus(approve.getStatus());
        reserveTaskDO.setRemarks(flowTaskDTO.getReviewComments());
        CgnciClaimReserveDO cgnciClaimReserveDO = this.baseMapper.selectOne(new LambdaQueryWrapper<CgnciClaimReserveDO>()
                .eq(CgnciClaimReserveDO::getTaskNo, flowTaskDTO.getTaskNo()));
        cgnciClaimReserveDO.setTaskStatus(approve.getStatus());
        cgnciClaimReserveDO.setUpdateTime(new Date());
        this.updateById(cgnciClaimReserveDO);
        reserveTaskMapper.updateById(reserveTaskDO);
        //更新镜像案件任务表状态-我的工作台任务列表用到
        updateCaseTask(flowTaskDTO.getTaskNo(), approve.getStatus(), user);
        if (1 == approve.getIsEnd()) {//流程审核结束更新准备金金额
            // TODO 更新准备金历史表状态
            LambdaUpdateWrapper<CgnciClaimReserveHistoryDO> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.eq(CgnciClaimReserveHistoryDO::getCaseNo, reserveTaskDO.getCaseNo());
            updateWrapper.eq(CgnciClaimReserveHistoryDO::getTaskNo, reserveTaskDO.getTaskNo());
            updateWrapper.set(CgnciClaimReserveHistoryDO::getTaskStatus, ClaimTaskStatusEnum.DONE.getCode());
            claimReserveHistoryService.update(updateWrapper);

            List<CgnciClaimReserveDetailTaskDO> reserveDetailTaskDO = reserveDetailTaskMapper.selectList(new LambdaQueryWrapper<CgnciClaimReserveDetailTaskDO>()
                    .eq(CgnciClaimReserveDetailTaskDO::getTaskNo, flowTaskDTO.getTaskNo()));
            for (CgnciClaimReserveDetailTaskDO detailTaskDO : reserveDetailTaskDO) {
                // 更新准备金详情最新调整准备金金额为0,将更新后的准备金金额替换已批准准备金金额
                CgnciClaimReserveDetailDO updateDetailDO = new CgnciClaimReserveDetailDO();

                updateDetailDO.setBeforeSettlementReserve(detailTaskDO.getApprovedReserve());
                updateDetailDO.setSettlementReserve(detailTaskDO.getAdjustReserve());
                updateDetailDO.setAfterSettlementReserve(detailTaskDO.getAfterAdjustReserve());
                updateDetailDO.setBeforeOriginalReserve(detailTaskDO.getApprovedReserveOriginal());
                updateDetailDO.setOriginalReserve(detailTaskDO.getAdjustReserveOriginal());
                updateDetailDO.setAfterOriginalReserve(detailTaskDO.getAfterAdjustReserveOriginal());

                updateDetailDO.setApprovedReserve(detailTaskDO.getAfterAdjustReserve());
                updateDetailDO.setAdjustReserve(new BigDecimal(0));
                updateDetailDO.setAfterAdjustReserve(detailTaskDO.getAfterAdjustReserve());
                updateDetailDO.setApprovedReserveOriginal(detailTaskDO.getAfterAdjustReserveOriginal());
                updateDetailDO.setAdjustReserveOriginal(new BigDecimal(0));
                updateDetailDO.setAfterAdjustReserveOriginal(detailTaskDO.getAfterAdjustReserveOriginal());
                reserveDetailMapper.update(updateDetailDO, new LambdaQueryWrapper<CgnciClaimReserveDetailDO>()
                        .eq(CgnciClaimReserveDetailDO::getReserveId, cgnciClaimReserveDO.getReserveId())
                        .eq(CgnciClaimReserveDetailDO::getRiskType, detailTaskDO.getRiskType()));
            }
            String content = String.format("立案号：%s;准备金计提/调整任务号：%s", reserveTaskDO.getCaseNo(), flowTaskDTO.getTaskNo());
            saveLog(reserveTaskDO.getCaseNo(), OperationTypeEnum.RESERVE_TASK_PASS, user.getUsername(), content);
        }
    }

    @Override
    public void back(CgnciClaimCaseCheckDTO flowTaskDTO) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();
        // 校验是否存在
        CgnciClaimReserveTaskDO reserveTaskDO = reserveTaskMapper.selectOne(
                new LambdaQueryWrapper<CgnciClaimReserveTaskDO>()
                        .eq(CgnciClaimReserveTaskDO::getTaskNo, flowTaskDTO.getTaskNo())
        );
        if (VerifyUtils.isEmpty(reserveTaskDO)) {
            throw new GlobalException(ResponseCodeEnum.PARAMS_ILLEGAL);
        }

        FlowTaskBackDTO taskBackDTO = new FlowTaskBackDTO();
        taskBackDTO.setFormId(flowTaskDTO.getTaskNo());
        taskBackDTO.setFormNo(flowTaskDTO.getTaskNo());
        taskBackDTO.setApprovalNode(flowTaskDTO.getApprovalNode());
        flowTaskDTO.setUserName(user.getUsername());
        FlowTaskVO back = approvalService.back(taskBackDTO);
        // 回调审批通过状态流程
        reserveTaskDO.setTaskStatus(String.valueOf(back.getStatus()));
        reserveTaskDO.setRemarks(flowTaskDTO.getReviewComments());
        CgnciClaimReserveDO cgnciClaimReserveDO = ConvertUtils.convert(reserveTaskDO, CgnciClaimReserveDO.class);
        this.update(cgnciClaimReserveDO, new LambdaQueryWrapper<CgnciClaimReserveDO>().eq(CgnciClaimReserveDO::getCaseNo, cgnciClaimReserveDO.getCaseNo()));
        reserveTaskMapper.updateById(reserveTaskDO);
        updateCaseTask(flowTaskDTO.getTaskNo(), back.getStatus(), user);
        String content = String.format("立案号：%s;准备金计提/调整任务号：%s", reserveTaskDO.getCaseNo(), flowTaskDTO.getTaskNo());
        saveLog(reserveTaskDO.getCaseNo(), OperationTypeEnum.RESERVE_TASK_BACK, user.getUsername(), content);
    }

    private void updateCaseTask(String taskNo, String TaskStatus, UserEntity user) {
        //更新镜像案件任务表状态-我的工作台任务列表用到
        CgnciClaimCaseTaskDO updaCaseDO = new CgnciClaimCaseTaskDO();
        updaCaseDO.setTaskStatus(TaskStatus);
        updaCaseDO.setUpdater(user.getNameAndCode());
        updaCaseDO.setUpdateTime(new Date());
        claimCaseTaskMapper.update(updaCaseDO, new LambdaQueryWrapper<CgnciClaimCaseTaskDO>().eq(CgnciClaimCaseTaskDO::getTaskNo, taskNo));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancel(String taskId) {
        // 获取当前登录用户
        UserEntity user = UserContext.getUser();

        // 校验任务是否存在
        /*CgnciApprovalInfoDO approvalInfo = approvalInfoMapper.selectById(taskId);
        if (VerifyUtils.isEmpty(approvalInfo)) {
            throw new GlobalException(ResponseCodeEnum.PARAMS_ILLEGAL, "taskId有误");
        }*/
        // 校验是否存在
        CgnciClaimReserveTaskDO reserveTaskDO = reserveTaskMapper.selectOne(
                new LambdaQueryWrapper<CgnciClaimReserveTaskDO>()
                        .eq(CgnciClaimReserveTaskDO::getTaskNo, taskId)
        );
        if (VerifyUtils.isEmpty(reserveTaskDO)) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR);
        }
        if (!"2".equals(reserveTaskDO.getTaskStatus())) {
            throw new GlobalException(ResponseCodeEnum.HTTP_REQUEST_SERVICE_ERROR, "当前状态不能注销");
        }
        // 更新准备金状态0:录入中,1:审核中,2:退回录入中,3:已注销,4:已完成
        reserveTaskDO.setTaskStatus("3");
        reserveTaskDO.setUpdater(user.getNameAndCode());
        reserveTaskMapper.updateById(reserveTaskDO);

        // 删除准备金历史
        cgnciClaimReserveHistoryService.remove(new LambdaQueryWrapper<CgnciClaimReserveHistoryDO>()
                .eq(CgnciClaimReserveHistoryDO::getTaskNo, taskId));

        //获取最新一条审核通过的数据
        CgnciClaimReserveTaskDO reserveTask = reserveTaskMapper.selectOne(
                new LambdaQueryWrapper<CgnciClaimReserveTaskDO>()
                        .eq(CgnciClaimReserveTaskDO::getTaskStatus, "4")
                        .eq(CgnciClaimReserveTaskDO::getCaseNo, reserveTaskDO.getCaseNo())
                        .orderByDesc(CgnciClaimReserveTaskDO::getCreateTime) // 按创建时间降序排列
                        .last("LIMIT 1") // 确保只返回一条记录
        );
        CgnciClaimReserveDO claimReserveDO = this.baseMapper.selectOne(new LambdaQueryWrapper<CgnciClaimReserveDO>()
                .eq(CgnciClaimReserveDO::getCaseNo, reserveTaskDO.getCaseNo()));
        if (Objects.isNull(reserveTask)) {
            this.removeById(claimReserveDO.getReserveId());
            reserveDetailMapper.delete(new LambdaQueryWrapper<CgnciClaimReserveDetailDO>()
                    .eq(CgnciClaimReserveDetailDO::getReserveId, claimReserveDO.getReserveId()));
            // 删除附件
            accessoryService.remove(new LambdaQueryWrapper<CgnciAccessoryDO>()
                    .eq(CgnciAccessoryDO::getBusinessNo, reserveTaskDO.getCaseNo())
                    .eq(CgnciAccessoryDO::getUploadNode, ClaimFlowEnum.CLAIM_RESERVE.getCode()));
        } else {
            CgnciClaimReserveDO updateReserveDO = ConvertUtils.convert(reserveTask, CgnciClaimReserveDO.class);
            this.update(updateReserveDO, new LambdaQueryWrapper<CgnciClaimReserveDO>().eq(CgnciClaimReserveDO::getCaseNo, updateReserveDO.getCaseNo()));

            List<CgnciClaimReserveDetailTaskDO> reserveDetailTaskDO = reserveDetailTaskMapper.selectList(new LambdaQueryWrapper<CgnciClaimReserveDetailTaskDO>()
                    .eq(CgnciClaimReserveDetailTaskDO::getTaskNo, reserveTask.getTaskNo()));
            //先删除再新增
            reserveDetailMapper.delete(new LambdaQueryWrapper<CgnciClaimReserveDetailDO>()
                    .eq(CgnciClaimReserveDetailDO::getReserveId, claimReserveDO.getReserveId()));
            for (CgnciClaimReserveDetailTaskDO detailTaskDO : reserveDetailTaskDO) {
                CgnciClaimReserveDetailDO reserveDetailDO = ConvertUtils.convert(detailTaskDO, CgnciClaimReserveDetailDO.class);
                reserveDetailDO.setDetailId(null);
                reserveDetailDO.setReserveId(claimReserveDO.getReserveId());

                reserveDetailDO.setBeforeSettlementReserve(detailTaskDO.getApprovedReserve());
                reserveDetailDO.setSettlementReserve(detailTaskDO.getAdjustReserve());
                reserveDetailDO.setAfterSettlementReserve(detailTaskDO.getAfterAdjustReserve());
                reserveDetailDO.setBeforeOriginalReserve(detailTaskDO.getApprovedReserveOriginal());
                reserveDetailDO.setOriginalReserve(detailTaskDO.getAdjustReserveOriginal());
                reserveDetailDO.setAfterOriginalReserve(detailTaskDO.getAfterAdjustReserveOriginal());


                // 取上一次批准的准备金金额
                reserveDetailDO.setApprovedReserve(reserveDetailDO.getAfterAdjustReserve());
                reserveDetailDO.setAdjustReserve(BigDecimal.ZERO);
                reserveDetailDO.setAfterAdjustReserve(reserveDetailDO.getAfterAdjustReserve());
                reserveDetailDO.setApprovedReserveOriginal(reserveDetailDO.getAfterAdjustReserveOriginal());
                reserveDetailDO.setAdjustReserveOriginal(BigDecimal.ZERO);
                reserveDetailDO.setAfterAdjustReserveOriginal(reserveDetailDO.getAfterAdjustReserveOriginal());
                reserveDetailMapper.insert(reserveDetailDO);
            }
        }
        // 注销审批流程
        approvalService.cancelTask(FlowTaskCancelDTO.builder()
                .formId(taskId)
                .formNo(taskId)
                .build());
        //更新任务关联案件状态
        updateCaseTask(taskId, ClaimTaskStatusEnum.LOG_OFF.getCode(), user);
        String content = String.format("立案号：%s;准备金计提/调整任务号：%s", reserveTaskDO.getCaseNo(), taskId);
        saveLog(reserveTaskDO.getCaseNo(), OperationTypeEnum.CANCEL_RESERVE, user.getUsername(), content);
    }

    @Override
    public List<ApprovalRecordVO> log(Long caseId) {
        List<CgnciApprovalRecordDO> approvalRecordDOList = approvalRecordMapper.selectList(
                new LambdaQueryWrapper<CgnciApprovalRecordDO>()
                        .eq(CgnciApprovalRecordDO::getFormId, caseId)
        );
        return ConvertUtils.convert(approvalRecordDOList, ApprovalRecordVO.class);
    }

    @Override
    public IPage<ReserveDetailTaskVO> reserveDetail(ReserveDetailQueryDTO req) {
        return reserveDetailTaskMapper.detailPage(req.toPage(), req);
    }

    @Override
    public BigDecimal reserveCollect(String caseNo, Date periodDnd, String isOd) {
        //获取最新一条审核通过的数据
        List<ReserveDetailTaskVO> detailTaskVOS = reserveDetailTaskMapper.queryDetail(caseNo, periodDnd, isOd);
        if (Objects.isNull(detailTaskVOS)) {
            return new BigDecimal(0);
        }
        return BeanUtils.sumBigDecimalProperty(detailTaskVOS, ReserveDetailTaskVO::getAdjustReserve);
    }

    private void saveLog(String caseNo, OperationTypeEnum typeEnum, String creator, String... remarks) {
        Assert.notNull(typeEnum, "操作类型必填");
        CgnciOperationLogsDTO saveLog = new CgnciOperationLogsDTO();
        if (Objects.nonNull(remarks)) {
            String content = String.join(ClaimConstant.SEMICOLON, remarks);
            saveLog.setContent(content);
        }
        Date now = new Date();
        saveLog.setBizNo(caseNo);
        saveLog.setBizType(BusinessScenariosEnum.CLAIM.getCode());
        saveLog.setOperationType(typeEnum.getCode());
        saveLog.setCreateTime(now);
        saveLog.setCreator(creator);
        saveLog.setUpdateTime(now);
        saveLog.setUpdater(creator);
        cgnciOperationLogsService.saveLog(saveLog);
    }
}
